package pool;

import handler.CacheHandler;
import handler.Handler;
import handler.HandlerManager;
import http.MyHttpRequest;
import util.MyUtil;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 每一个accept得到的socket请求都会对应一个这样的writeTask
 *在这个线程依次取出request，选择本代理服务器配置文件中适合的处理器，去完成转发的作用
 * @author Karl
 * @Date 2023/1/2 - 14:39
 */
//读数据线程负责读取远程数据后回写到客户端
public class WriteTask implements Runnable {

    private Socket remote, local;

//    private static String lineReg = "HTTP\\/[0-9]\\.[0-9]\\s+[0-9]{3}\\s+[\\s\\S]*";

    private BlockingQueue<MyHttpRequest> requests = new LinkedBlockingQueue<>();
//    private BlockingQueue<MyHttpRequest> done = new LinkedBlockingQueue<>();


    public WriteTask(Socket local, MyHttpRequest request) throws IOException {
        //根据request去连接
        this.local = local;
        remote = new Socket(request.getHost(), request.getPort());
            requests.add(request);
//            remote.setSoTimeout(10000);
    }

    public boolean addRequest(MyHttpRequest request) {
        return requests.offer(request);

    }



    public Socket getRemote() {
        return remote;
    }


    public Socket getLocal() {
        return local;
    }

    public void setLocal(Socket local) {
        this.local = local;
    }

    @Override
    public void run() {

        //是否已经发送给remote，一开始就不考虑使用缓存了
        boolean isSendToRemote = false;
        MyHttpRequest request = null;
        int sleepTime = 50;

        try {
            while (!local.isClosed()) {
                while ((request = requests.poll(sleepTime, TimeUnit.MILLISECONDS)) == null) {
                    sleepTime += 10;
                    if (sleepTime > 600) return;
                }
                sleepTime = 50;
                //查找适合的处理器去进行处理
                Handler handler = HandlerManager.getHandlerAdapter(request,remote);
                assert handler != null;
                //如果是connectHandle,会在里面死循环出不来的
                if (handler.handler(request, local, remote)) {
                    return;
                }
//                done.offer(request);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            MyUtil.closeIo(local);
            MyUtil.closeIo(remote);
        }

    }


    public static boolean writeToFile(RandomAccessFile random, byte b) {
        try {
            random.writeByte(b);
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    public static boolean writeToFile(RandomAccessFile random, byte[] buf, int off, int len) {
        try {
            random.write(buf, off, len);
        } catch (IOException e) {
            return false;
        }
        return true;
    }


}
